import { ElementPropertyConfig } from '@farris/ide-property-panel';
import { UniformEditorDataUtil } from '@farris/designer-services';
import { CodeEditorComponent } from '@farris/designer-devkit';
import { FormPropertyChangeObject } from '../../../../entity/property-change-entity';
import { InputProps } from '../../common/property/input-property-config';

export class NumericBoxProp extends InputProps {

    propertyConfig: ElementPropertyConfig[];

    getPropConfig(propertyData: any): ElementPropertyConfig[] {

        this.propertyConfig = [];

        // 基本信息属性
        const basicPropConfig = this.getBasicPropConfig(propertyData, this.viewModelId);
        this.propertyConfig.push(basicPropConfig);

        // 外观属性
        const appearanceProperties = this.getAppearancePropConfig(propertyData, this.viewModelId);
        this.propertyConfig.push(appearanceProperties);

        // 行为属性
        const behaviorPropConfig = this.getBehaviorPropConfig(propertyData, this.viewModelId);
        this.propertyConfig.push(behaviorPropConfig);

        // 扩展区域属性
        // const appendPropConfig = this.getInputAppendPropertyConfig(propertyData, this.viewModelId);
        // this.propertyConfig.push(appendPropConfig);

        // 表达式属性
        const exprPropConfig = this.getExpressionPropConfig(propertyData, this.viewModelId);
        if (exprPropConfig) {
            this.propertyConfig.push(exprPropConfig);
        }
        // 事件属性
        const eventPropConfig = this.getEventPropertyConfig(propertyData, this.viewModelId);
        this.propertyConfig.push(eventPropConfig);

        return this.propertyConfig;
    }

    public getBasicPropConfig(propertyData: any, viewModelId: string, showPosition = 'card'): ElementPropertyConfig {

        const basicProperties = this.getBasicCommonPropConfig(propertyData);
        basicProperties.push(
            {
                propertyID: 'controlSource',
                propertyName: '控件来源',
                propertyType: 'select',
                description: '组件的控件来源',
                iterator: [{ key: 'Farris', value: 'Farris' }, { key: 'Kendo', value: 'Kendo' }],
                refreshPanelAfterChanged: true,
                visible: showPosition === 'card' && propertyData.controlSource !== 'Farris'
            }
        );
        const self = this;
        return {
            categoryId: 'basic',
            categoryName: '基本信息',
            properties: basicProperties,
            setPropertyRelates(changeObject: FormPropertyChangeObject, prop, parameters) {

                if (!changeObject) {
                    return;
                }
                switch (changeObject.propertyID) {
                    case 'type': {
                        self.changeControlType(propertyData, changeObject.propertyValue);
                        break;
                    }
                    case 'controlSource': {

                        // 变更【外观分类】下的属性
                        const newAppearancePropConfig = self.getAppearancePropConfig(propertyData, viewModelId);
                        const currentAppearanceConfig = self.propertyConfig.find(cat => cat.categoryId === 'appearance');
                        Object.assign(currentAppearanceConfig, newAppearancePropConfig);

                        // 变更【行为分类】下的属性
                        const newBehaviorPropConfig = self.getBehaviorPropConfig(propertyData, viewModelId);
                        const currentBehaviorConfig = self.propertyConfig.find(cat => cat.categoryId === 'behavior');
                        Object.assign(currentBehaviorConfig, newBehaviorPropConfig);

                    }
                }

            },

        };
    }


    private getAppearancePropConfig(propertyData: any, viewModelId: string, showPosition = 'card'): ElementPropertyConfig {
        const self = this;
        let appearanceProperties = [];

        if (showPosition === 'card' || showPosition === 'tableTdEditor') {
            appearanceProperties = this.getAppearanceCommonPropConfig(propertyData, viewModelId, showPosition);

            appearanceProperties.push(
                {
                    propertyID: 'textAlign',
                    propertyName: '数据水平对齐方式',
                    propertyType: 'select',
                    description: '数据水平对齐方式设置',
                    defaultValue: 'left',
                    iterator: [{ key: 'left', value: '靠左' }, { key: 'right', value: '靠右' }, { key: 'center', value: '居中' }],
                    visible: propertyData.controlSource === 'Farris',
                    controlSource: 'Farris'
                },
                {
                    propertyID: 'formatter',
                    propertyName: '格式化',
                    propertyType: 'modal',
                    description: '格式化设置',
                    editor: CodeEditorComponent,
                    editorParams: {
                        language: 'javascript',
                        exampleCode:
                            "\r\n (value: number): string | number => {\r\n    return '$' + value;\r\n}\r\n"
                    },
                    visible: propertyData.controlSource === 'Farris',
                    controlSource: 'Farris'
                },
                {
                    propertyID: 'parser',
                    propertyName: '反格式化',
                    propertyType: 'modal',
                    description: '反格式化设置',
                    editor: CodeEditorComponent,
                    editorParams: {
                        language: 'javascript',
                        exampleCode:
                            "\r\n (value: string):number => {\r\n    return  Number(value.substring(1));\r\n}\r\n"
                    },
                    visible: propertyData.controlSource === 'Farris',
                    controlSource: 'Farris'
                }
            );
        }

        appearanceProperties.push(
            {
                propertyID: 'showButton',
                propertyName: '显示微调按钮',
                propertyType: 'boolean',
                description: '是否显示微调按钮',
                controlSource: 'Farris'
            },
            {
                propertyID: 'showZero',
                propertyName: '显示0值',
                propertyType: 'boolean',
                description: '是否显示0值',
                controlSource: 'Farris'
            },
            {
                propertyID: 'canNull',
                propertyName: '显示空值',
                propertyType: 'boolean',
                description: '是否允许显示空值'
            },
            {
                propertyID: 'format',
                propertyName: '格式',
                propertyType: 'string',
                description: '格式设置',
                visible: !propertyData.controlSource || propertyData.controlSource === 'Kendo',
                controlSource: 'Kendo'
            }
        );

        const config = {
            categoryId: 'appearance',
            categoryName: '外观',
            properties: appearanceProperties,
            setPropertyRelates(changeObject: FormPropertyChangeObject, prop, parameters) {

                if (!changeObject) {
                    return;
                }
                self.changeAppearancePropertyRelates(this.properties, changeObject, propertyData, parameters);

            },

        };
        if (showPosition !== 'card') {
            Object.assign(config, {
                categoryId: showPosition + '_' + config.categoryId,
                propertyData,
                enableCascade: true,
                parentPropertyID: 'editor',
                tabId: showPosition,
                tabName: '编辑器'
            });
        }
        return config;
    }

    private getBehaviorPropConfig(propertyData: any, viewModelId: string, showPosition = 'card'): ElementPropertyConfig {
        // 获取绑定字段长度和精度
        let maxLength;
        let maxPrecision;
        if (propertyData.binding && propertyData.binding.type === 'Form') {
            const fieldInfo = this.schemaService.getFieldByIDAndVMID(propertyData.binding.field, viewModelId);
            if (fieldInfo && fieldInfo.schemaField) {
                maxLength = fieldInfo.schemaField.type.length;
                maxPrecision = fieldInfo.schemaField.type.precision;
            }
        }
        let behaviorProperties = [];
        if (showPosition === 'card' || showPosition === 'tableTdEditor') {
            behaviorProperties = this.getBehaviorCommonPropConfig(propertyData, viewModelId);
        }
        behaviorProperties.push(
            {
                propertyID: 'maxLength',
                propertyName: '取值最大长度',
                propertyType: 'number',
                description: '数字取值最大长度',
                decimals: 0,
                min: 0,
                max: maxLength
            },
            {
                propertyID: 'maxValue',
                propertyName: '最大值',
                propertyType: 'number',
                description: '数字最大值',
                min: propertyData.minValue ? propertyData.minValue : undefined,
                decimals: propertyData.precision,
                isBigNumber: propertyData.bigNumber
            },
            {
                propertyID: 'minValue',
                propertyName: '最小值',
                propertyType: 'number',
                description: '数字最小值',
                max: propertyData.maxValue ? propertyData.maxValue : undefined,
                decimals: propertyData.precision,
                isBigNumber: propertyData.bigNumber
            },
            {
                propertyID: 'step',
                propertyName: '步长',
                propertyType: 'number',
                description: '步长设置',
                min: 0
            },
            {
                propertyID: 'precisionSourceType',
                propertyName: '精度类型',
                propertyType: 'select',
                description: '精度类型选择',
                iterator: [{ key: 'static', value: '静态' }, { key: 'dynamic', value: '动态' }],
                visible: propertyData.controlSource === 'Farris' && maxPrecision !== 0,
                controlSource: 'Farris'
            },
            {
                propertyID: 'precision',
                propertyName: '精度',
                propertyType: 'number',
                description: '数字精度',
                decimals: 0,
                min: 0,
                max: maxPrecision,
                visible: propertyData.controlSource === 'Farris' && propertyData.precisionSourceType === 'static',
                controlSource: 'Farris'
            },
            {
                propertyID: 'precisionDataSource',
                propertyName: '精度',
                propertyType: 'unity',
                description: '数字精度数据源设置',
                editorParams: {
                    controlName: UniformEditorDataUtil.getControlName(propertyData),
                    editorOptions: {
                        types: ['variable'],
                        variables: UniformEditorDataUtil.getVariables(viewModelId, this.domService),
                        getVariables: () => UniformEditorDataUtil.getVariables(viewModelId, this.domService)
                    }
                },
                visible: propertyData.controlSource === 'Farris' && propertyData.precisionSourceType === 'dynamic'
            },
            {
                propertyID: 'useThousands',
                propertyName: '使用千分值',
                propertyType: 'boolean',
                description: '是否使用千分值',
                defaultValue: true,
                visible: propertyData.controlSource === 'Farris',
                controlSource: 'Farris'
            },
            {
                propertyID: 'bigNumber',
                propertyName: '是否大数值',
                propertyType: 'boolean',
                description: '是否为大数值',
                readonly: true
            }
        );

        const self = this;
        const config = {
            categoryId: 'behavior',
            categoryName: '行为',
            properties: behaviorProperties,
            setPropertyRelates(changeObject: FormPropertyChangeObject, data, parameters) {
                if (!changeObject) {
                    return;
                }
                self.changeBehaviorPropertyRelates(this.properties, changeObject, propertyData, parameters, showPosition);

                switch (changeObject && changeObject.propertyID) {
                    case 'maxValue': {
                        const minProp = this.properties.find(p => p.propertyID === 'minValue');
                        if (minProp) {
                            minProp.max = changeObject.propertyValue ? changeObject.propertyValue : undefined;
                        }
                        break;
                    }
                    case 'minValue': {
                        const maxProp = this.properties.find(p => p.propertyID === 'maxValue');
                        if (maxProp) {
                            maxProp.min = changeObject.propertyValue ? changeObject.propertyValue : undefined;
                        }
                        break;
                    }
                    case 'precision': {
                        const maxProp = this.properties.find(p => p.propertyID === 'maxValue');
                        if (maxProp) {
                            maxProp.decimals = changeObject.propertyValue;
                        }
                        const minProp = this.properties.find(p => p.propertyID === 'minValue');
                        if (minProp) {
                            minProp.decimals = changeObject.propertyValue;
                        }
                        break;
                    }
                    case 'precisionSourceType': {
                        const precision = this.properties.find(p => p.propertyID === 'precision');
                        if (precision) {
                            precision.visible = propertyData.controlSource === 'Farris' && changeObject.propertyValue === 'static';
                        }
                        const precisionDataSource = this.properties.find(p => p.propertyID === 'precisionDataSource');
                        if (precisionDataSource) {
                            precisionDataSource.visible =
                                propertyData.controlSource === 'Farris' && changeObject.propertyValue === 'dynamic';
                        }
                        break;
                    }

                }
            }

        };
        if (showPosition !== 'card') {
            Object.assign(config, {
                categoryId: showPosition + '_' + config.categoryId,
                propertyData,
                enableCascade: true,
                parentPropertyID: 'editor',
                tabId: showPosition,
                tabName: '编辑器'
            });
        }
        return config;
    }
    /**
     * 列编辑器属性
     * @param gridFieldData 列数据
     */
    getGridFieldEdtiorPropConfig(gridFieldData: any, viewModelId: string) {
        const propertyData = gridFieldData.editor;

        this.propertyConfig = [];

        // 编辑器类型属性
        const editorTypeConfig = this.getGridFieldEditorTypePropertyConfig(gridFieldData, viewModelId);
        if (editorTypeConfig) {
            this.propertyConfig.push(editorTypeConfig);
        }

        // 外观属性
        const apperanceConfig = this.getAppearancePropConfig(propertyData, viewModelId, 'gridFieldEditor');
        this.propertyConfig.push(apperanceConfig);

        // 行为属性
        const behaviorConfig = this.getBehaviorPropConfig(propertyData, viewModelId, 'gridFieldEditor');
        this.appendBehaviorPropsForGridFieldEditor(behaviorConfig, propertyData, viewModelId);
        this.propertyConfig.push(behaviorConfig);

        // 事件属性
        const eventPropConfig = this.getEventPropertyConfig(propertyData, this.viewModelId, 'gridFieldEditor');
        this.propertyConfig.push(eventPropConfig);

        return this.propertyConfig;
    }

    /**
     * table单元格编辑器属性
     * @param tdData 单元格数据
     * @param viewModelId viewModelId
     * @returns 属性配置
     */
    getTableTdEdtiorPropConfig(tdData: any, viewModelId: string): ElementPropertyConfig[] {
        const propertyData = tdData.editor;

        this.propertyConfig = [];

        // 外观属性
        const appearanceConfig = this.getAppearancePropConfig(propertyData, viewModelId, 'tableTdEditor');
        this.propertyConfig.push(appearanceConfig);

        // 行为属性
        const behaviorConfig = this.getBehaviorPropConfig(propertyData, viewModelId, 'tableTdEditor');
        behaviorConfig.properties = behaviorConfig.properties.filter(p => !'binding,visible'.includes(p.propertyID));
        this.propertyConfig.push(behaviorConfig);

        // 扩展区域属性
        const appendPropConfig = this.getInputAppendPropertyConfig(propertyData, viewModelId, 'tableTdEditor');
        this.propertyConfig.push(appendPropConfig);

        // 表达式属性
        const exprPropConfig = this.getExpressionPropConfig(propertyData, viewModelId, 'tableTdEditor');
        if (exprPropConfig) {
            this.propertyConfig.push(exprPropConfig);
        }

        // 事件属性
        const eventPropConfig = this.getEventPropertyConfig(propertyData, this.viewModelId, 'tableTdEditor');
        this.propertyConfig.push(eventPropConfig);

        return this.propertyConfig;
    }

}
